﻿using Catel.Data;

#if !SILVERLIGHT
using System;
using System.Runtime.Serialization;
#endif

namespace Catel.Articles._04___Unit_testing.Models
{
    using System.Collections.Generic;
    using System.ComponentModel;

    #region Enums
    /// <summary>
    /// Gender of a person.
    /// </summary>
    public enum Gender
    {
        /// <summary>
        /// Unknown.
        /// </summary>
        Unknown,

        /// <summary>
        /// Male.
        /// </summary>
        Male,

        /// <summary>
        /// Female.
        /// </summary>
        Female
    }
    #endregion

    /// <summary>
    /// Person Data object class which fully supports serialization, property changed notifications,
    /// backwards compatibility and error checking.
    /// </summary>
#if !SILVERLIGHT
    [Serializable]
#endif
    public class Person : DataObjectBase<Person>
    {
        #region Variables
        #endregion

        #region Constructor & destructor
        /// <summary>
        /// Initializes a new object from scratch.
        /// </summary>
        public Person()
        { }

#if !SILVERLIGHT
        /// <summary>
        /// Initializes a new object based on <see cref="SerializationInfo"/>.
        /// </summary>
        /// <param name="info"><see cref="SerializationInfo"/> that contains the information.</param>
        /// <param name="context"><see cref="StreamingContext"/>.</param>
        protected Person(SerializationInfo info, StreamingContext context)
            : base(info, context) { }
#endif
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the first name.
        /// </summary>
        public string FirstName
        {
            get { return GetValue<string>(FirstNameProperty); }
            set { SetValue(FirstNameProperty, value); }
        }

        /// <summary>
        /// Register the property so it is known in the class.
        /// </summary>
        public readonly PropertyData FirstNameProperty = RegisterProperty("FirstName", typeof(string), string.Empty,
            (sender, e) => ((Person)sender).RaisePropertyChanged("FullName"));

        /// <summary>
        /// Gets or sets the middle name.
        /// </summary>
        public string MiddleName
        {
            get { return GetValue<string>(MiddleNameProperty); }
            set { SetValue(MiddleNameProperty, value); }
        }

        /// <summary>
        /// Register the property so it is known in the class.
        /// </summary>
        public readonly PropertyData MiddleNameProperty = RegisterProperty("MiddleName", typeof(string), string.Empty,
            (sender, e) => ((Person)sender).RaisePropertyChanged("FullName"));

        /// <summary>
        /// Gets or sets the last name.
        /// </summary>
        public string LastName
        {
            get { return GetValue<string>(LastNameProperty); }
            set { SetValue(LastNameProperty, value); }
        }

        /// <summary>
        /// Register the property so it is known in the class.
        /// </summary>
        public readonly PropertyData LastNameProperty = RegisterProperty("LastName", typeof(string), string.Empty,
            (sender, e) => ((Person)sender).RaisePropertyChanged("FullName"));

        /// <summary>
        /// Gets or sets the gender.
        /// </summary>
        public Gender Gender
        {
            get { return GetValue<Gender>(GenderProperty); }
            set { SetValue(GenderProperty, value); }
        }

        /// <summary>
        /// Register the property so it is known in the class.
        /// </summary>
        public readonly PropertyData GenderProperty = RegisterProperty("Gender", typeof(Gender), Gender.Unknown);

        public string FullName
        {
            get 
            {
                string fullName = FirstName;

                if (!string.IsNullOrEmpty(MiddleName))
                {
                    if (!string.IsNullOrEmpty(fullName))
                    {
                        fullName += " ";
                    }

                    fullName += MiddleName;
                }

                if (!string.IsNullOrEmpty(LastName))
                {
                    if (!string.IsNullOrEmpty(fullName))
                    {
                        fullName += " ";
                    }

                    fullName += LastName;
                }

                return fullName;
            }
        }
        #endregion

        #region Methods
        protected override void ValidateFields(List<FieldValidationResult> validationResults)
        {
            if (string.IsNullOrEmpty(FirstName))
            {
                validationResults.Add(FieldValidationResult.CreateError(FirstNameProperty, "First name is required"));
            }

            if (string.IsNullOrEmpty(LastName))
            {
                validationResults.Add(FieldValidationResult.CreateError(LastNameProperty, "Last name is required"));
            }

            if (Gender == Gender.Unknown)
            {
                validationResults.Add(FieldValidationResult.CreateError(GenderProperty, "Gender cannot be unknown"));
            }
        }
        #endregion
    }
}
